Neon Dawn | 24/05/2020

Neon Dawn was the first game I made in the 3D space. I like to think it is a Mirrors Edge / Superhot hybrid, where you're wall running, grappling and taking down enemies as you try to make it to dawn.

Short demonstration video of the game

As I mentioned in the video, the bits of code I'm most happy with are the utility pieces. The SettingsMaster, MusicManager, LevelChanger and ProgressManager scripts follow a singleton structure and are very versatile so I will be sure to take them into my future projects. These scripts can be viewed in full on my Github.

Settings Master:

SettingsMaster.cs Script

  • Stores the players data via PlayerPrefs.
  • Uses a number of static methods for getting / setting the values.
  • Easy intergration with all future SettingsManager (what I like to call the front end of my settings system, ie: the buttons / sliders to actually change the controls / values) scripts.

Music Manager:

MusicManager.cs Script

  • Easy to add / remove songs and simple to create new methods to trigger songs for different areas (currently just has PlayMenuMusic() and PlayLevelMusic() methods).
  • Quality of life methods and coroutines such as pick a random song and fade int / out music.
  • Works with the SettingsMaster for volume control.

Level Changer:

LevelChanger.cs Script

  • Provides a scene transition for moving between levels.
  • Provides a radial loading bar for scenes which will take longer to load via LoadSceneAsync.
  • Easy change the effect due to the use of animation and triggers.

Progress Manager / SaveData:

ProgressManager.cs Script

  • Progress Manager is responsible for saving and loading level data.
  • Works with the serializable SaveData class in conjunction with a binary formatter.
  • Works with the LevelManager and UpdateLevelsLocked scripts though this functionality can easily be removed / updated for a different style of game.

---

I'm also happy with my PlayerMovement script.

PlayerMovement.cs Script

This script is by far the longest of the project and works in conjunction with the HudManager script as well as the inbuilt CharacterController component to provide all the functionality the player needs. Its a state machine and I think it is one of the best pieces of code I've written so far. Compared to my Stick Battle player controller script it is both easier to read (and therefore update) and more efficient. Furthermore, like the utility code, it is easy to modify and will be simple to integrate into any future projects if need be.

One thing that I think could be improved is the UpdateHealth() method of the HudManager script. I feel like this code is rather messy, and a primary reason for this is that I got frustrated as I had been trying to make it work for several hours. The working solution uses a lot of if statements, and so while the in game effect looks good the code certainly doesn't.

HudManager.cs Script | Updating Health Gif

My basic approach was to have two parts to each health segment. The inside bit, the 'bar', would be shifted back which each health segment lost and the outline would be set to inactive. I think a refactored and better approach would be to use the inbuilt UI outline component instead of a separate gameobject.

---

As for the actual game, in the demo scene I showcased the components that would end up in a level:

Wall Running:

Wall Run Gif

Wall running would be a large part of Neon Dawn so it is important that the system for it worked well. My wall running script works in three stages. First, in the Update() method, raycasts are fired out to either side of the player at foot level. If the raycasts hit a wall tagged WallRunWall and the distance to said wall is less than or equal to WALL_RUN_DISTANCE then the isWallRunning bool is set to true. This means that the players y position is frozen. Finally the coroutine SmoothCameraRotate() is called, rotating the camera +/- 20 degrees depending on if the player is wall running on the right or left side. When the player leaves a wall, the camera rotation is reset (once again via SmoothCameraRotate()) and the players y position is unfrozen.

Grappling:

Grapple Gif

To implement a grappling hook I followed Code Monkeys grappling hook tutorial. It works via states so was easy to implement into my existing structure as I had already decided to try a state machine approach with Neon Dawn. Additions I made to Code Monkeys code include a grapple cooldown and integration with the HudManager.

Raising Walls:

Raising Walls Gif

Definitly something simple, but an important part of Neon Dawns levels nevertheless. In order to make the game more interesting the player would often find themselves stranded on rooftops, pinned down by enemy fire. The combination of a button to raise walls, giving the player the cover they need to deal with the enemies, and powercubes to buy the player more time would have added a fairly unique mechanic to Neon Dawn and distanced it further from existing runner style games.

Enemies:

Rifle Enemy Gif | Sniper Enemy Gif

I was especially happy with the implementation of the enemies in Neon Dawn. Both the rifle and sniper enemy have the BasicEnemyBehaviour script which manages their colour, movement and collisions. Then a separate RifleEnemy or SniperEnemy script dictates their specific behaviour. The rifle enemy simiply checks the distance between the player and itself via a raycast and if the player is both in range and not behind a wall instantiates a bullet prefab (which is possible to dodge). The sniper enemy is a little more complex, first checking if it is in range and has line of site but then locking on. Once the sniper has locked on to the player they have 3 seconds to either get out of range or find cover before the sniper fires. This effect was primarily accomplished through the use of coroutines, and instead of spawning a bullet damage is dealt immediately.

---

I mentioned in the video that Neon Dawn has taught me what my strengths and weaknesses are, and this combined with Stick Battle helping me consolidate my coding style I feel like I'm now ready to make something publishable.